﻿#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <iomanip>
#include <algorithm>
#include <chrono>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

const int QR_SIZE = 41;
const int LOCATOR_SIZE = 7;
const unsigned char START_END_MARKER = 0xAA;
const int SCALE_FACTOR = 10;

// 颜色定义 - 与编码器一致
enum Color {
    WHITE = 0,  // 白色 - 00
    BLACK = 1,  // 黑色 - 01  
    RED = 2,    // 红色 - 10
    BLUE = 3,   // 蓝色 - 11
    GREEN = 4   // 绿色 - 用于定位标记
};

// 解码配置
struct DecoderConfig {
    double originalFPS = 10.0;    // 原始视频帧率
    bool enableFrameSkip = true;  // 启用帧跳过
    bool enablePreprocessing = true; // 启用图像预处理
    bool useHSVColorSpace = true; // 使用HSV颜色空间
    int samplingArea = 7;         // 采样区域大小
    int preStartFrames = 10;      // 起始标记前处理的帧数
    bool enablePerspectiveCorrection = true; // 启用透视校正
    bool enableWhiteBalance = true; // 启用白平衡
};

class VideoDecoder {
private:
    VideoCapture cap;
    int totalFrames;
    int currentFrame;
    DecoderConfig config;

public:
    VideoDecoder(const string& videoPath, const DecoderConfig& cfg = DecoderConfig()) : config(cfg) {
        cap.open(videoPath);
        if (!cap.isOpened()) {
            throw runtime_error("Cannot open video file: " + videoPath);
        }

        totalFrames = static_cast<int>(cap.get(CAP_PROP_FRAME_COUNT));
        currentFrame = 0;
    }

    ~VideoDecoder() {
        if (cap.isOpened()) {
            cap.release();
        }
    }

    bool getNextFrame(Mat& frame) {
        if (currentFrame >= totalFrames) {
            return false;
        }

        bool success = cap.read(frame);
        if (success) {
            currentFrame++;
        }
        return success;
    }

    int getTotalFrames() const { return totalFrames; }
    int getCurrentFrame() const { return currentFrame; }

    double getFPS() const {
        return cap.get(CAP_PROP_FPS);
    }

    // 计算应该跳过的帧数
    int calculateFrameSkip() const {
        if (!config.enableFrameSkip) return 1;

        double phoneFPS = getFPS();
        int skip = static_cast<int>(round(phoneFPS / config.originalFPS));
        return max(1, skip); // 至少为1
    }
};

bool verifyCRC(unsigned char data, unsigned char receivedCRC) {
    unsigned char calculatedCRC = 0;
    unsigned char polynomial = 0x07;

    calculatedCRC ^= data;
    for (int i = 0; i < 8; i++) {
        if (calculatedCRC & 0x80) {
            calculatedCRC = (calculatedCRC << 1) ^ polynomial;
        }
        else {
            calculatedCRC <<= 1;
        }
    }

    return calculatedCRC == receivedCRC;
}

// 白平衡校正
Mat whiteBalance(const Mat& frame) {
    Mat result;
    vector<Mat> channels;
    split(frame, channels);

    // 简单的灰度世界白平衡
    double avg_r = mean(channels[2])[0];
    double avg_g = mean(channels[1])[0];
    double avg_b = mean(channels[0])[0];

    double avg = (avg_r + avg_g + avg_b) / 3.0;

    // 避免除零
    if (avg_r > 10) channels[2] = channels[2] * (avg / avg_r);
    if (avg_g > 10) channels[1] = channels[1] * (avg / avg_g);
    if (avg_b > 10) channels[0] = channels[0] * (avg / avg_b);

    merge(channels, result);

    // 限制像素值在0-255范围内
    result.convertTo(result, -1, 1.0, 0);
    return result;
}

// 透视校正
Mat perspectiveCorrection(const Mat& frame) {
    // 检测绿色定位标记
    Mat hsv, mask;
    cvtColor(frame, hsv, COLOR_BGR2HSV);

    // 绿色范围 - 放宽条件以适应不同光照
    Scalar lower_green(35, 40, 40);
    Scalar upper_green(85, 255, 255);
    inRange(hsv, lower_green, upper_green, mask);

    // 形态学操作
    Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5));
    morphologyEx(mask, mask, MORPH_CLOSE, kernel);
    morphologyEx(mask, mask, MORPH_OPEN, kernel);

    // 查找轮廓
    vector<vector<Point>> contours;
    findContours(mask, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);

    // 找到四个最大的轮廓（定位标记）
    if (contours.size() >= 4) {
        // 按面积排序
        sort(contours.begin(), contours.end(),
            [](const vector<Point>& a, const vector<Point>& b) {
                return contourArea(a) > contourArea(b);
            });

        vector<Point2f> corners;
        for (int i = 0; i < 4 && i < contours.size(); i++) {
            Moments m = moments(contours[i]);
            if (m.m00 != 0) {
                Point2f center(m.m10 / m.m00, m.m01 / m.m00);
                corners.push_back(center);
            }
        }

        if (corners.size() == 4) {
            // 对角点进行排序：左上、右上、左下、右下
            // 计算中心点
            Point2f center(0, 0);
            for (const auto& corner : corners) {
                center += corner;
            }
            center.x /= 4;
            center.y /= 4;

            // 分类角点
            vector<Point2f> sortedCorners(4);
            for (const auto& corner : corners) {
                if (corner.x < center.x && corner.y < center.y) {
                    sortedCorners[0] = corner; // 左上
                }
                else if (corner.x > center.x && corner.y < center.y) {
                    sortedCorners[1] = corner; // 右上
                }
                else if (corner.x < center.x && corner.y > center.y) {
                    sortedCorners[2] = corner; // 左下
                }
                else {
                    sortedCorners[3] = corner; // 右下
                }
            }

            // 计算透视变换
            vector<Point2f> dstCorners;
            dstCorners.push_back(Point2f(0, 0));
            dstCorners.push_back(Point2f(QR_SIZE * SCALE_FACTOR - 1, 0));
            dstCorners.push_back(Point2f(0, QR_SIZE * SCALE_FACTOR - 1));
            dstCorners.push_back(Point2f(QR_SIZE * SCALE_FACTOR - 1, QR_SIZE * SCALE_FACTOR - 1));

            Mat transform = getPerspectiveTransform(sortedCorners, dstCorners);
            Mat corrected;
            warpPerspective(frame, corrected, transform,
                Size(QR_SIZE * SCALE_FACTOR, QR_SIZE * SCALE_FACTOR));

            cout << "Perspective correction applied" << endl;
            return corrected;
        }
    }

    cout << "Perspective correction failed - using original frame" << endl;
    return Mat(); // 返回空矩阵表示未进行校正
}

// 图像预处理函数
Mat preprocessFrame(const Mat& frame, const DecoderConfig& config) {
    Mat processed = frame.clone();

    // 1. 透视校正
    if (config.enablePerspectiveCorrection) {
        Mat perspectiveCorrected = perspectiveCorrection(processed);
        if (!perspectiveCorrected.empty()) {
            processed = perspectiveCorrected;
        }
    }

    // 2. 白平衡校正
    if (config.enableWhiteBalance) {
        processed = whiteBalance(processed);
    }

    // 3. 锐化增强边缘
    Mat sharpened;
    Mat kernel = (Mat_<float>(3, 3) <<
        -1, -1, -1,
        -1, 9, -1,
        -1, -1, -1);
    filter2D(processed, sharpened, -1, kernel);
    processed = sharpened;

    // 4. 对比度增强
    Mat contrasted;
    processed.convertTo(contrasted, -1, 1.3, 10);
    processed = contrasted;

    // 5. 自适应直方图均衡化 - 分别处理每个通道
    vector<Mat> channels;
    split(processed, channels);
    for (int i = 0; i < 3; i++) {
        equalizeHist(channels[i], channels[i]);
    }
    Mat merged;
    merge(channels, merged);
    processed = merged;

    // 6. 双边滤波去噪（保留边缘）- 修复：不使用原地操作
    Mat filtered;
    bilateralFilter(processed, filtered, 5, 50, 50);
    processed = filtered;

    return processed;
}

// 基于RGB的颜色识别
Color detectColorRGB(const Vec3b& pixel) {
    int b = pixel[0];
    int g = pixel[1];
    int r = pixel[2];

    // 计算颜色强度差异
    int rg_diff = abs(r - g);
    int rb_diff = abs(r - b);
    int gb_diff = abs(g - b);

    // 绿色检测 - 放宽条件
    if (g > r + 30 && g > b + 30 && g > 100) {
        return GREEN;
    }

    // 白色检测 - 所有通道值都高且差异小
    if (r > 180 && g > 180 && b > 180 && rg_diff < 50 && rb_diff < 50) {
        return WHITE;
    }

    // 黑色检测 - 所有通道值都低
    if (r < 80 && g < 80 && b < 80) {
        return BLACK;
    }

    // 红色检测 - 红色明显高于绿色和蓝色
    if (r > g + 40 && r > b + 40 && r > 100) {
        return RED;
    }

    // 蓝色检测 - 蓝色明显高于红色和绿色
    if (b > r + 40 && b > g + 40 && b > 100) {
        return BLUE;
    }

    // 基于亮度判断
    int brightness = (r + g + b) / 3;
    if (brightness > 180) return WHITE;
    if (brightness < 80) return BLACK;

    // 基于色相判断
    if (r > max(g, b)) return RED;
    if (b > max(r, g)) return BLUE;

    // 默认返回白色
    return WHITE;
}

// 基于HSV的颜色识别（更鲁棒）
Color detectColorHSV(const Vec3b& pixel) {
    int b = pixel[0], g = pixel[1], r = pixel[2];

    // 转换为HSV
    Mat hsvPixel;
    Mat bgrPixel(1, 1, CV_8UC3, Scalar(b, g, r));
    cvtColor(bgrPixel, hsvPixel, COLOR_BGR2HSV);

    int h = hsvPixel.at<Vec3b>(0, 0)[0];
    int s = hsvPixel.at<Vec3b>(0, 0)[1];
    int v = hsvPixel.at<Vec3b>(0, 0)[2];

    // 基于HSV的颜色识别 - 放宽条件
    if (s < 30 && v > 200) return WHITE;    // 低饱和度，高亮度 → 白色
    if (v < 60) return BLACK;                // 低亮度 → 黑色

    // 红色（需要处理色相环绕）
    if ((h < 10 || h > 170) && s > 50 && v > 50) return RED;

    // 蓝色
    if (h > 100 && h < 140 && s > 50 && v > 50) return BLUE;

    // 绿色
    if (h > 35 && h < 85 && s > 50 && v > 50) return GREEN;

    // 基于亮度的后备方案
    int brightness = (r + g + b) / 3;
    if (brightness > 200) return WHITE;
    if (brightness < 60) return BLACK;

    // 基于RGB比例的后备方案
    if (r > g * 1.5 && r > b * 1.5) return RED;
    if (b > r * 1.5 && b > g * 1.5) return BLUE;

    return WHITE; // 默认
}

// 改进的颜色识别函数
Color detectColorRobust(const Vec3b& pixel, bool useHSV = true) {
    if (useHSV) {
        return detectColorHSV(pixel);
    }
    else {
        return detectColorRGB(pixel);
    }
}

// 颜色到比特的映射
vector<bool> colorToBits(Color color) {
    switch (color) {
    case WHITE: return { false, false };  // 00
    case BLACK: return { false, true };   // 01
    case RED:   return { true, false };   // 10
    case BLUE:  return { true, true };    // 11
    default:    return { false, false };  // 默认白色
    }
}

// 计算解码置信度
double calculateDecodingConfidence(const vector<bool>& bits) {
    if (bits.empty()) return 0.0;

    // 简单的置信度计算：检查是否有合理的比特模式
    int transitions = 0;
    for (size_t i = 1; i < bits.size(); i++) {
        if (bits[i] != bits[i - 1]) {
            transitions++;
        }
    }

    double transitionRatio = static_cast<double>(transitions) / bits.size();

    // 理想情况下应该有适度的比特转换率（既不全0也不全1）
    double confidence = 1.0 - abs(transitionRatio - 0.5) * 2.0;
    return max(0.0, confidence);
}

// 解码QR帧 - 支持手机录制优化
vector<bool> decodeQRFrame(const Mat& frame, const DecoderConfig& config, double& confidence) {
    vector<bool> bits;

    if (frame.empty()) {
        confidence = 0.0;
        return bits;
    }

    // 图像预处理
    Mat processedFrame = frame;
    if (config.enablePreprocessing) {
        processedFrame = preprocessFrame(frame, config);
    }

    int decodedPixels = 0;
    int samplingOffset = config.samplingArea / 2;

    // 统计颜色分布用于调试
    vector<int> colorStats(5, 0); // WHITE, BLACK, RED, BLUE, GREEN

    for (int logicalRow = 0; logicalRow < QR_SIZE; logicalRow++) {
        for (int logicalCol = 0; logicalCol < QR_SIZE; logicalCol++) {
            // 跳过定位标记区域
            if ((logicalRow < LOCATOR_SIZE && logicalCol < LOCATOR_SIZE) ||
                (logicalRow < LOCATOR_SIZE && logicalCol >= QR_SIZE - LOCATOR_SIZE) ||
                (logicalRow >= QR_SIZE - LOCATOR_SIZE && logicalCol < LOCATOR_SIZE) ||
                (logicalRow >= QR_SIZE - 5 && logicalCol >= QR_SIZE - 5)) {
                continue;
            }

            decodedPixels++;

            // 在原始帧中采样
            int centerY = logicalRow * SCALE_FACTOR + SCALE_FACTOR / 2;
            int centerX = logicalCol * SCALE_FACTOR + SCALE_FACTOR / 2;

            // 统计颜色投票
            vector<int> colorVotes(5, 0); // WHITE, BLACK, RED, BLUE, GREEN

            // 采样区域
            for (int y_offset = -samplingOffset; y_offset <= samplingOffset; y_offset++) {
                for (int x_offset = -samplingOffset; x_offset <= samplingOffset; x_offset++) {
                    int y = centerY + y_offset;
                    int x = centerX + x_offset;

                    if (y >= 0 && y < processedFrame.rows && x >= 0 && x < processedFrame.cols) {
                        Color detected = detectColorRobust(processedFrame.at<Vec3b>(y, x), config.useHSVColorSpace);
                        if (detected >= 0 && detected <= 4) {
                            colorVotes[detected]++;
                        }
                    }
                }
            }

            // 找到得票最多的颜色（排除绿色，因为数据区域不应有绿色）
            int maxVotes = 0;
            Color dominantColor = WHITE;

            for (int i = 0; i < 4; i++) { // 只考虑前4种颜色（WHITE, BLACK, RED, BLUE）
                if (colorVotes[i] > maxVotes) {
                    maxVotes = colorVotes[i];
                    dominantColor = static_cast<Color>(i);
                }
            }

            colorStats[dominantColor]++;

            // 将颜色转换为2个比特
            vector<bool> colorBits = colorToBits(dominantColor);
            bits.insert(bits.end(), colorBits.begin(), colorBits.end());
        }
    }

    // 计算置信度
    confidence = calculateDecodingConfidence(bits);

    // 输出调试信息
    cout << "Decoded pixels: " << decodedPixels << ", bits: " << bits.size()
        << ", confidence: " << fixed << setprecision(3) << confidence
        << ", Colors - W:" << colorStats[WHITE] << " B:" << colorStats[BLACK]
        << " R:" << colorStats[RED] << " U:" << colorStats[BLUE] << endl;

    return bits;
}

// 带重试机制的解码
vector<bool> decodeQRFrameWithRetry(const Mat& frame, const DecoderConfig& config) {
    vector<bool> bestResult;
    double bestConfidence = 0;

    // 尝试不同的预处理组合
    DecoderConfig tempConfig = config;

    // 尝试1: 默认配置
    cout << "Trying default configuration..." << endl;
    double confidence;
    vector<bool> result = decodeQRFrame(frame, tempConfig, confidence);
    if (confidence > bestConfidence) {
        bestConfidence = confidence;
        bestResult = result;
    }

    // 尝试2: 关闭预处理
    cout << "Trying without preprocessing..." << endl;
    tempConfig.enablePreprocessing = false;
    tempConfig.enablePerspectiveCorrection = false;
    tempConfig.enableWhiteBalance = false;
    result = decodeQRFrame(frame, tempConfig, confidence);
    if (confidence > bestConfidence) {
        bestConfidence = confidence;
        bestResult = result;
    }

    // 尝试3: 使用RGB颜色空间
    cout << "Trying RGB color space..." << endl;
    tempConfig = config;
    tempConfig.useHSVColorSpace = false;
    result = decodeQRFrame(frame, tempConfig, confidence);
    if (confidence > bestConfidence) {
        bestConfidence = confidence;
        bestResult = result;
    }

    // 尝试4: 更大的采样区域
    cout << "Trying larger sampling area..." << endl;
    tempConfig = config;
    tempConfig.samplingArea = 11;
    result = decodeQRFrame(frame, tempConfig, confidence);
    if (confidence > bestConfidence) {
        bestConfidence = confidence;
        bestResult = result;
    }

    cout << "Best decoding confidence: " << bestConfidence << endl;
    return bestResult;
}

vector<unsigned char> extractBytes(const vector<bool>& bitStream) {
    vector<unsigned char> bytes;

    if (bitStream.size() < 8) {
        return bytes;
    }

    for (size_t i = 0; i + 7 < bitStream.size(); i += 8) {
        unsigned char byte = 0;
        for (int j = 0; j < 8; j++) {
            byte = (byte << 1) | (bitStream[i + j] ? 1 : 0);
        }
        bytes.push_back(byte);
    }

    return bytes;
}

size_t findStartMarker(const vector<unsigned char>& data) {
    for (size_t i = 0; i + 7 < data.size(); i++) {
        bool found = true;
        for (int j = 0; j < 8; j++) {
            if (data[i + j] != START_END_MARKER) {
                found = false;
                break;
            }
        }
        if (found) {
            return i;
        }
    }
    return string::npos;
}

size_t findEndMarker(const vector<unsigned char>& data, size_t startPos) {
    for (size_t i = startPos + 8; i + 7 < data.size(); i++) {
        bool found = true;
        for (int j = 0; j < 8; j++) {
            if (data[i + j] != START_END_MARKER) {
                found = false;
                break;
            }
        }
        if (found) {
            return i;
        }
    }
    return string::npos;
}

// 处理数据并验证CRC
void processDataWithValidation(const vector<unsigned char>& payload,
    vector<unsigned char>& data,
    vector<bool>& validation) {
    data.clear();
    validation.clear();

    // 每两个字节：数据字节 + CRC字节
    for (size_t i = 0; i + 1 < payload.size(); i += 2) {
        unsigned char dataByte = payload[i];
        unsigned char crcByte = payload[i + 1];

        bool isValid = verifyCRC(dataByte, crcByte);

        // 添加数据字节
        data.push_back(dataByte);

        // 为数据字节的每个比特添加验证信息
        for (int bit = 7; bit >= 0; bit--) {
            validation.push_back(isValid);
        }
    }
}

// 将比特验证信息转换为字节
vector<unsigned char> convertValidationToBytes(const vector<bool>& validationBits) {
    vector<unsigned char> validationBytes;

    if (validationBits.size() < 8) {
        return validationBytes;
    }

    for (size_t i = 0; i + 7 < validationBits.size(); i += 8) {
        unsigned char byte = 0;
        for (int j = 0; j < 8; j++) {
            byte = (byte << 1) | (validationBits[i + j] ? 1 : 0);
        }
        validationBytes.push_back(byte);
    }

    return validationBytes;
}

// 计算传输速率 (kb/s)
double calculateTransmissionRate(int dataSizeBytes, double videoDuration, int totalFrames) {
    if (videoDuration <= 0) return 0.0;

    // 总传输数据量（包括开销）：原始数据 + CRC字节 + 标记字节
    // 每个数据字节有1个CRC字节，加上16个标记字节（8起始+8结束）
    int totalTransmittedBytes = dataSizeBytes * 2 + 16;
    double dataRateKbps = (totalTransmittedBytes * 8) / (videoDuration * 1000.0); // kb/s

    return dataRateKbps;
}

// 以十六进制格式输出字节数据
void printHexData(const vector<unsigned char>& data, const string& title, int bytesPerLine = 16) {
    cout << title << " (" << data.size() << " bytes):" << endl;

    for (size_t i = 0; i < data.size(); i++) {
        cout << hex << setw(2) << setfill('0') << (int)data[i] << " ";

        if ((i + 1) % bytesPerLine == 0) {
            cout << endl;
        }
    }

    if (data.size() % bytesPerLine != 0) {
        cout << endl;
    }
    cout << dec << endl;
}

// 检查是否找到起始标记的早期迹象
bool hasStartMarkerEarlySign(const vector<unsigned char>& data, size_t checkSize = 100) {
    if (data.size() < 8) return false;

    size_t checkEnd = min(data.size(), checkSize);
    for (size_t i = 0; i + 7 < checkEnd; i++) {
        bool found = true;
        for (int j = 0; j < 8; j++) {
            if (data[i + j] != START_END_MARKER) {
                found = false;
                break;
            }
        }
        if (found) {
            return true;
        }
    }
    return false;
}

// 保存调试图像
void saveDebugImage(const Mat& frame, const string& filename) {
    static int counter = 0;
    string debugFilename = "debug_" + to_string(counter++) + "_" + filename;
    imwrite(debugFilename, frame);
    cout << "Saved debug image: " << debugFilename << endl;
}

// 查找部分起始标记（用于调试）
void findPartialMarkers(const vector<unsigned char>& data) {
    cout << "Searching for partial start markers..." << endl;

    // 查找连续的0xAA模式
    for (size_t i = 0; i + 3 < data.size(); i++) {
        if (data[i] == START_END_MARKER &&
            data[i + 1] == START_END_MARKER &&
            data[i + 2] == START_END_MARKER) {

            cout << "Found 3+ consecutive 0xAA at position " << i << endl;

            // 打印上下文
            int start = max(0, (int)i - 5);
            int end = min((int)data.size(), (int)i + 15);
            cout << "Context: ";
            for (int j = start; j < end; j++) {
                cout << hex << setw(2) << setfill('0') << (int)data[j] << " ";
            }
            cout << dec << endl;
        }
    }
}

// 尝试直接提取数据（假设起始标记在视频之外）
void attemptDirectExtraction(const vector<unsigned char>& allBytes,
    const string& outputDataFile,
    const string& outputValidationFile) {
    cout << "Attempting direct data extraction..." << endl;

    // 假设数据从某个位置开始，尝试不同的偏移量
    for (int offset = 0; offset < 100 && offset < allBytes.size(); offset++) {
        vector<unsigned char> testData;
        vector<bool> validationBits;

        // 从偏移位置开始处理数据
        for (size_t i = offset; i + 1 < allBytes.size(); i += 2) {
            unsigned char dataByte = allBytes[i];
            unsigned char crcByte = allBytes[i + 1];

            bool isValid = verifyCRC(dataByte, crcByte);
            testData.push_back(dataByte);

            for (int bit = 7; bit >= 0; bit--) {
                validationBits.push_back(isValid);
            }
        }

        if (!testData.empty()) {
            // 检查提取的数据是否合理（包含可打印字符或常见文件头）
            int validCount = 0;
            for (unsigned char byte : testData) {
                if (byte >= 32 && byte <= 126) { // 可打印ASCII
                    validCount++;
                }
            }

            double validRatio = (double)validCount / testData.size();
            cout << "Offset " << offset << ": " << testData.size()
                << " bytes, valid ratio: " << validRatio << endl;

            if (validRatio > 0.7) { // 如果大部分是可打印字符
                cout << "*** POTENTIAL DATA FOUND AT OFFSET " << offset << " ***" << endl;

                // 保存这个可能的数据
                vector<unsigned char> validationBytes = convertValidationToBytes(validationBits);

                ofstream dataFile(outputDataFile, ios::binary);
                if (dataFile.is_open()) {
                    dataFile.write(reinterpret_cast<const char*>(testData.data()), testData.size());
                    dataFile.close();
                    cout << "Data saved to: " << outputDataFile << endl;
                }

                ofstream validationFile(outputValidationFile, ios::binary);
                if (validationFile.is_open()) {
                    validationFile.write(reinterpret_cast<const char*>(validationBytes.data()), validationBytes.size());
                    validationFile.close();
                    cout << "Validation data saved to: " << outputValidationFile << endl;
                }

                return; // 找到一个可能的数据就返回
            }
        }
    }

    // 如果没有找到合理的数据，保存原始字节流的前半部分
    cout << "No valid data found, saving first half of decoded bytes..." << endl;

    vector<unsigned char> data;
    vector<bool> validationBits;

    // 只取前半部分数据
    size_t halfSize = allBytes.size() / 2;
    for (size_t i = 0; i + 1 < halfSize; i += 2) {
        unsigned char dataByte = allBytes[i];
        unsigned char crcByte = allBytes[i + 1];

        bool isValid = verifyCRC(dataByte, crcByte);
        data.push_back(dataByte);

        for (int bit = 7; bit >= 0; bit--) {
            validationBits.push_back(isValid);
        }
    }

    vector<unsigned char> validationBytes = convertValidationToBytes(validationBits);

    ofstream dataFile(outputDataFile, ios::binary);
    if (dataFile.is_open()) {
        dataFile.write(reinterpret_cast<const char*>(data.data()), data.size());
        dataFile.close();
        cout << "Data saved to: " << outputDataFile << " (" << data.size() << " bytes)" << endl;
    }

    ofstream validationFile(outputValidationFile, ios::binary);
    if (validationFile.is_open()) {
        validationFile.write(reinterpret_cast<const char*>(validationBytes.data()), validationBytes.size());
        validationFile.close();
        cout << "Validation data saved to: " << outputValidationFile << " (" << validationBytes.size() << " bytes)" << endl;
    }
}

// 处理找到的数据
void processFoundData(const vector<unsigned char>& allBytes, size_t startPos,
    const string& outputDataFile, const string& outputValidationFile) {

    size_t endPos = findEndMarker(allBytes, startPos);
    if (endPos != string::npos) {
        cout << "Found end marker at position: " << endPos << endl;

        // 提取有效载荷
        vector<unsigned char> payload;
        for (size_t i = startPos + 8; i < endPos; i++) {
            payload.push_back(allBytes[i]);
        }

        cout << "Payload size: " << payload.size() << " bytes" << endl;

        // 处理数据并获取验证信息
        vector<unsigned char> data;
        vector<bool> validationBits;
        processDataWithValidation(payload, data, validationBits);
        vector<unsigned char> validationBytes = convertValidationToBytes(validationBits);

        cout << "Valid data: " << data.size() << " bytes" << endl;

        // 保存文件
        ofstream dataFile(outputDataFile, ios::binary);
        if (dataFile.is_open()) {
            dataFile.write(reinterpret_cast<const char*>(data.data()), data.size());
            dataFile.close();
            cout << "Data saved to: " << outputDataFile << endl;
        }

        ofstream validationFile(outputValidationFile, ios::binary);
        if (validationFile.is_open()) {
            validationFile.write(reinterpret_cast<const char*>(validationBytes.data()), validationBytes.size());
            validationFile.close();
            cout << "Validation data saved to: " << outputValidationFile << endl;
        }

        // 显示前几个字节用于验证
        cout << "First 32 data bytes: ";
        for (size_t i = 0; i < min((size_t)32, data.size()); i++) {
            cout << hex << setw(2) << setfill('0') << (int)data[i] << " ";
        }
        cout << dec << endl;
    }
    else {
        cout << "No end marker found after start marker" << endl;

        // 即使没有结束标记，也尝试提取数据
        vector<unsigned char> payload;
        for (size_t i = startPos + 8; i < allBytes.size(); i++) {
            payload.push_back(allBytes[i]);
        }

        cout << "Extracted payload size: " << payload.size() << " bytes" << endl;

        // 处理数据并获取验证信息
        vector<unsigned char> data;
        vector<bool> validationBits;
        processDataWithValidation(payload, data, validationBits);
        vector<unsigned char> validationBytes = convertValidationToBytes(validationBits);

        cout << "Valid data: " << data.size() << " bytes" << endl;

        // 保存文件
        ofstream dataFile(outputDataFile, ios::binary);
        if (dataFile.is_open()) {
            dataFile.write(reinterpret_cast<const char*>(data.data()), data.size());
            dataFile.close();
            cout << "Data saved to: " << outputDataFile << endl;
        }

        ofstream validationFile(outputValidationFile, ios::binary);
        if (validationFile.is_open()) {
            validationFile.write(reinterpret_cast<const char*>(validationBytes.data()), validationBytes.size());
            validationFile.close();
            cout << "Validation data saved to: " << outputValidationFile << endl;
        }
    }
}

int main(int argc, char* argv[]) {
    if (argc < 4) {
        cout << "Usage: decode input_video.mp4 output_data.bin output_validation.bin [original_fps]" << endl;
        cout << "Example: decode out.mp4 out.bin vout.bin 10" << endl;
        return -1;
    }

    string inputVideo = argv[1];
    string outputDataFile = argv[2];
    string outputValidationFile = argv[3];

    // 配置解码器
    DecoderConfig config;
    if (argc >= 5) {
        config.originalFPS = stod(argv[4]);
    }

    // 针对手机视频的优化配置
    config.enablePreprocessing = false;
    config.enablePerspectiveCorrection = false;
    config.enableWhiteBalance = false;
    config.useHSVColorSpace = false;
    config.samplingArea = 3;
    config.preStartFrames = 0;
    config.enableFrameSkip = false;

    try {
        VideoDecoder decoder(inputVideo, config);
        double phoneFPS = decoder.getFPS();
        int totalFrames = decoder.getTotalFrames();
        double videoDuration = totalFrames / phoneFPS;

        cout << "=== Robust Video Decoder ===" << endl;
        cout << "Input video: " << inputVideo << endl;
        cout << "Output data file: " << outputDataFile << endl;
        cout << "Output validation file: " << outputValidationFile << endl;
        cout << "Phone recording FPS: " << phoneFPS << endl;
        cout << "Original video FPS: " << config.originalFPS << endl;
        cout << "Total frames: " << totalFrames << endl;
        cout << "Video duration: " << fixed << setprecision(2) << videoDuration << " seconds" << endl;
        cout << "Preprocessing: " << (config.enablePreprocessing ? "ENABLED" : "DISABLED") << endl;
        cout << "Perspective correction: " << (config.enablePerspectiveCorrection ? "ENABLED" : "DISABLED") << endl;
        cout << "White balance: " << (config.enableWhiteBalance ? "ENABLED" : "DISABLED") << endl;
        cout << "Color space: " << (config.useHSVColorSpace ? "HSV" : "RGB") << endl;
        cout << "Sampling area: " << config.samplingArea << "x" << config.samplingArea << endl;

        // 收集所有帧的数据
        vector<bool> allBits;
        Mat frame;
        int processedFrames = 0;
        int decodedFrames = 0;

        cout << "\nProcessing frames..." << endl;

        auto startTime = chrono::high_resolution_clock::now();

        while (decoder.getNextFrame(frame)) {
            processedFrames++;
            decodedFrames++;

            if (processedFrames % 10 == 0) {
                cout << "Processing frame " << processedFrames << "/" << totalFrames << endl;
            }

            vector<bool> bits = decodeQRFrameWithRetry(frame, config);
            allBits.insert(allBits.end(), bits.begin(), bits.end());
        }

        auto endTime = chrono::high_resolution_clock::now();
        chrono::duration<double> decodingTime = endTime - startTime;

        cout << "\n=== Decoding Summary ===" << endl;
        cout << "Total frames processed: " << processedFrames << endl;
        cout << "Total frames decoded: " << decodedFrames << endl;
        cout << "Total bits collected: " << allBits.size() << endl;

        vector<unsigned char> allBytes = extractBytes(allBits);
        cout << "Total bytes after extraction: " << allBytes.size() << endl;

        // 查找数据
        size_t startPos = findStartMarker(allBytes);
        if (startPos != string::npos) {
            cout << "Found start marker at position: " << startPos << endl;
            processFoundData(allBytes, startPos, outputDataFile, outputValidationFile);
        }
        else {
            cout << "No start marker found" << endl;
            findPartialMarkers(allBytes);
            attemptDirectExtraction(allBytes, outputDataFile, outputValidationFile);
        }

        cout << "\n=== Decoding Complete ===" << endl;
        cout << "Total frames processed: " << processedFrames << endl;
        cout << "Total frames decoded: " << decodedFrames << endl;
        cout << "Decoding time: " << decodingTime.count() << " seconds" << endl;

    }
    catch (const exception& e) {
        cerr << "Error: " << e.what() << endl;

        // 即使出错也要创建输出文件（空文件）
        ofstream dataFile(outputDataFile, ios::binary);
        dataFile.close();

        ofstream validationFile(outputValidationFile, ios::binary);
        validationFile.close();

        return -1;
    }

    return 0;
}